/*      */ package com.zimbra.cs.imap;
/*      */ 
/*      */ import com.google.common.base.Charsets;
/*      */ import com.google.common.collect.ImmutableMap;
/*      */ import com.google.common.collect.ImmutableMap.Builder;
/*      */ import com.google.common.collect.ImmutableSet;
/*      */ import com.zimbra.common.localconfig.KnownKey;
/*      */ import com.zimbra.common.localconfig.LC;
/*      */ import com.zimbra.common.util.Log;
/*      */ import com.zimbra.common.util.ZimbraLog;
/*      */ import java.io.ByteArrayOutputStream;
/*      */ import java.io.IOException;
/*      */ import java.nio.ByteBuffer;
/*      */ import java.nio.CharBuffer;
/*      */ import java.nio.charset.Charset;
/*      */ import java.util.ArrayList;
/*      */ import java.util.Calendar;
/*      */ import java.util.Date;
/*      */ import java.util.GregorianCalendar;
/*      */ import java.util.HashMap;
/*      */ import java.util.List;
/*      */ import java.util.Map;
/*      */ import java.util.Set;
/*      */ import org.apache.commons.codec.binary.Base64;
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ abstract class ImapRequest
/*      */ {
/*   57 */   private static final boolean[] TAG_CHARS = new boolean[''];
/*   58 */   private static final boolean[] ATOM_CHARS = new boolean[''];
/*   59 */   private static final boolean[] ASTRING_CHARS = new boolean[''];
/*   60 */   private static final boolean[] PATTERN_CHARS = new boolean[''];
/*   61 */   private static final boolean[] FETCH_CHARS = new boolean[''];
/*   62 */   private static final boolean[] NUMBER_CHARS = new boolean[''];
/*   63 */   private static final boolean[] SEQUENCE_CHARS = new boolean[''];
/*   64 */   private static final boolean[] BASE64_CHARS = new boolean[''];
/*   65 */   private static final boolean[] SEARCH_CHARS = new boolean[''];
/*      */   private static final int LAST_PUNCT = 0; private static final int LAST_DIGIT = 1; private static final int LAST_STAR = 2; private static final Set<String> SYSTEM_FLAGS; private static final Map<String, String> NEGATED_SEARCH; private static final boolean SINGLE_CLAUSE = true; private static final boolean MULTIPLE_CLAUSES = false; private static final String SUBCLAUSE = "";
/*   67 */   static { for (int i = 33; i < 127; i++) {
/*   68 */       if ((i != 40) && (i != 41) && (i != 123) && (i != 37) && (i != 42) && (i != 34) && (i != 92)) {
/*   69 */         SEARCH_CHARS[i] = (FETCH_CHARS[i] = PATTERN_CHARS[i] = ASTRING_CHARS[i] = ATOM_CHARS[i] = TAG_CHARS[i] = 1);
/*      */       }
/*      */     }
/*   72 */     ATOM_CHARS[93] = false;
/*   73 */     TAG_CHARS[43] = false;
/*   74 */     PATTERN_CHARS[37] = (PATTERN_CHARS[42] = 1);
/*   75 */     FETCH_CHARS[91] = false;
/*   76 */     SEARCH_CHARS[42] = true;
/*      */     
/*   78 */     for (int i = 97; i <= 122; i++) {
/*   79 */       BASE64_CHARS[i] = true;
/*      */     }
/*   81 */     for (int i = 65; i <= 90; i++) {
/*   82 */       BASE64_CHARS[i] = true;
/*      */     }
/*   84 */     for (int i = 48; i <= 57; i++) {
/*   85 */       BASE64_CHARS[i] = (NUMBER_CHARS[i] = SEQUENCE_CHARS[i] = 1);
/*      */     }
/*   87 */     SEQUENCE_CHARS[42] = (SEQUENCE_CHARS[58] = SEQUENCE_CHARS[44] = SEQUENCE_CHARS[36] = 1);
/*   88 */     BASE64_CHARS[43] = (BASE64_CHARS[47] = 1);
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*   93 */     SYSTEM_FLAGS = ImmutableSet.of("ANSWERED", "FLAGGED", "DELETED", "SEEN", "DRAFT");
/*   94 */     NEGATED_SEARCH = ImmutableMap.builder().put("ANSWERED", "UNANSWERED").put("DELETED", "UNDELETED").put("DRAFT", "UNDRAFT").put("FLAGGED", "UNFLAGGED").put("KEYWORD", "UNKEYWORD").put("RECENT", "OLD").put("OLD", "RECENT").put("SEEN", "UNSEEN").put("UNANSWERED", "ANSWERED").put("UNDELETED", "DELETED").put("UNDRAFT", "DRAFT").put("UNFLAGGED", "FLAGGED").put("UNKEYWORD", "KEYWORD").put("UNSEEN", "SEEN").build();
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  115 */     ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
/*  116 */     String[] names = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
/*  117 */     for (int i = 0; i < names.length; i++) {
/*  118 */       builder.put(names[i], Integer.valueOf(i));
/*      */     }
/*  120 */     MONTH_NUMBER = builder.build(); }
/*      */   
/*      */   private static final Map<String, Integer> MONTH_NUMBER;
/*      */   static final boolean NONZERO = false;
/*      */   static final boolean ZERO_OK = true;
/*      */   final ImapHandler mHandler;
/*      */   String tag;
/*  127 */   List<Part> parts = new ArrayList();
/*      */   int index;
/*      */   int offset;
/*      */   private boolean isAppend;
/*      */   private boolean isLogin;
/*      */   private final int maxNestingInSearchRequest;
/*      */   
/*      */   ImapRequest(ImapHandler handler) {
/*  135 */     this.mHandler = handler;
/*  136 */     this.maxNestingInSearchRequest = LC.imap_max_nesting_in_search_request.intValue();
/*      */   }
/*      */   
/*      */   ImapRequest rewind() {
/*  140 */     this.index = (this.offset = 0);
/*  141 */     return this; }
/*      */   
/*      */   protected abstract class Part { protected Part() {}
/*      */     
/*      */     abstract int size();
/*      */     
/*      */     abstract byte[] getBytes() throws IOException;
/*      */     
/*      */     abstract String getString() throws ImapParseException;
/*      */     abstract Literal getLiteral() throws ImapParseException;
/*  151 */     boolean isString() { return false; }
/*      */     
/*      */     boolean isLiteral()
/*      */     {
/*  155 */       return false;
/*      */     }
/*      */     
/*      */     void cleanup() {}
/*      */   }
/*      */   
/*      */   private final class StringPart extends ImapRequest.Part {
/*      */     private final String str;
/*      */     
/*      */     StringPart(String s) {
/*  165 */       super();
/*  166 */       this.str = s;
/*      */     }
/*      */     
/*      */     int size()
/*      */     {
/*  171 */       return this.str.length();
/*      */     }
/*      */     
/*      */     byte[] getBytes()
/*      */     {
/*  176 */       return this.str.getBytes();
/*      */     }
/*      */     
/*      */     boolean isString()
/*      */     {
/*  181 */       return true;
/*      */     }
/*      */     
/*      */     String getString()
/*      */     {
/*  186 */       return this.str;
/*      */     }
/*      */     
/*      */     public String toString()
/*      */     {
/*  191 */       return this.str;
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*  196 */     Literal getLiteral() throws ImapParseException { throw new ImapParseException(ImapRequest.this.tag, "not inside literal"); }
/*      */   }
/*      */   
/*      */   private final class LiteralPart extends ImapRequest.Part {
/*      */     private final Literal lit;
/*      */     
/*      */     LiteralPart(Literal l) {
/*  203 */       super();
/*  204 */       this.lit = l;
/*      */     }
/*      */     
/*      */     int size()
/*      */     {
/*  209 */       return this.lit.size();
/*      */     }
/*      */     
/*      */     byte[] getBytes() throws IOException
/*      */     {
/*  214 */       return this.lit.getBytes();
/*      */     }
/*      */     
/*      */     boolean isLiteral()
/*      */     {
/*  219 */       return true;
/*      */     }
/*      */     
/*      */     Literal getLiteral()
/*      */     {
/*  224 */       return this.lit;
/*      */     }
/*      */     
/*      */     void cleanup()
/*      */     {
/*  229 */       this.lit.cleanup();
/*      */     }
/*      */     
/*      */     public String getString() throws ImapParseException
/*      */     {
/*  234 */       throw new ImapParseException(ImapRequest.this.tag, "not inside string");
/*      */     }
/*      */     
/*      */     public String toString()
/*      */     {
/*      */       try {
/*  240 */         return new String(this.lit.getBytes(), Charsets.US_ASCII);
/*      */       } catch (IOException e) {}
/*  242 */       return "???";
/*      */     }
/*      */   }
/*      */   
/*      */   void addPart(Literal literal)
/*      */   {
/*  248 */     addPart(new LiteralPart(literal));
/*      */   }
/*      */   
/*      */   void addPart(String line) {
/*  252 */     if (this.parts.isEmpty()) {
/*  253 */       String cmd = getCommand(line);
/*  254 */       if ("APPEND".equalsIgnoreCase(cmd)) {
/*  255 */         this.isAppend = true;
/*  256 */       } else if ("LOGIN".equalsIgnoreCase(cmd)) {
/*  257 */         this.isLogin = true;
/*      */       }
/*      */     }
/*  260 */     addPart(new StringPart(line));
/*      */   }
/*      */   
/*      */   void addPart(Part part) {
/*  264 */     this.parts.add(part);
/*      */   }
/*      */   
/*      */   void cleanup() {
/*  268 */     for (Part part : this.parts) {
/*  269 */       part.cleanup();
/*      */     }
/*  271 */     this.parts.clear();
/*      */   }
/*      */   
/*      */   protected boolean isAppend() {
/*  275 */     return this.isAppend;
/*      */   }
/*      */   
/*      */   protected boolean isLogin() {
/*  279 */     return this.isLogin;
/*      */   }
/*      */   
/*      */   protected String getCommand(String requestLine) {
/*  283 */     int i = requestLine.indexOf(' ') + 1;
/*  284 */     if (i > 0) {
/*  285 */       int j = requestLine.indexOf(' ', i);
/*  286 */       if (j > 0) {
/*  287 */         return requestLine.substring(i, j);
/*      */       }
/*      */     }
/*  290 */     return null;
/*      */   }
/*      */   
/*      */   String getCurrentLine() throws ImapParseException {
/*  294 */     return ((Part)this.parts.get(this.index)).getString();
/*      */   }
/*      */   
/*      */   byte[] toByteArray() throws IOException {
/*  298 */     ByteArrayOutputStream baos = new ByteArrayOutputStream();
/*  299 */     for (Part part : this.parts) {
/*  300 */       byte[] content = part.getBytes();
/*  301 */       baos.write(content, 0, content.length);
/*  302 */       if (part.isString()) {
/*  303 */         baos.write(ImapHandler.LINE_SEPARATOR_BYTES, 0, 2);
/*      */       }
/*      */     }
/*  306 */     return baos.toByteArray();
/*      */   }
/*      */   
/*      */   String getTag()
/*      */   {
/*  311 */     if ((this.tag == null) && (this.index == 0) && (this.offset == 0) && (this.parts.size() > 0)) {
/*      */       try {
/*  313 */         readTag();
/*      */       }
/*      */       catch (ImapParseException ignore) {}
/*  316 */       this.index = 0;
/*  317 */       this.offset = 0;
/*      */     }
/*  319 */     return this.tag;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   boolean extensionEnabled(String extension)
/*      */   {
/*  328 */     return (this.mHandler == null) || (this.mHandler.extensionEnabled(extension));
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   void setTag(String value)
/*      */   {
/*  336 */     this.tag = value;
/*      */   }
/*      */   
/*      */   String readContent(boolean[] acceptable) throws ImapParseException
/*      */   {
/*  341 */     return readContent(acceptable, false);
/*      */   }
/*      */   
/*      */   String readContent(boolean[] acceptable, boolean emptyOK) throws ImapParseException {
/*  345 */     String content = getCurrentLine();
/*      */     
/*  347 */     for (int i = this.offset; i < content.length(); i++) {
/*  348 */       char c = content.charAt(i);
/*  349 */       if ((c > '') || (acceptable[c] == 0)) {
/*      */         break;
/*      */       }
/*      */     }
/*  353 */     if ((i == this.offset) && (!emptyOK)) {
/*  354 */       throw new ImapParseException(this.tag, "zero-length content");
/*      */     }
/*  356 */     String result = content.substring(this.offset, i);
/*  357 */     this.offset += result.length();
/*  358 */     return result;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   boolean eof()
/*      */   {
/*  366 */     return (this.index >= this.parts.size()) || (this.offset >= ((Part)this.parts.get(this.index)).size());
/*      */   }
/*      */   
/*      */ 
/*      */   int peekChar()
/*      */     throws ImapParseException
/*      */   {
/*  373 */     if (this.index >= this.parts.size()) {
/*  374 */       return -1;
/*      */     }
/*  376 */     String str = ((Part)this.parts.get(this.index)).getString();
/*  377 */     return this.offset < str.length() ? str.charAt(this.offset) : -1;
/*      */   }
/*      */   
/*      */   String peekATOM() {
/*  381 */     int i = this.index;
/*  382 */     int o = this.offset;
/*      */     try {
/*  384 */       return readATOM();
/*      */     } catch (ImapParseException ipe) {
/*  386 */       return null;
/*      */     } finally {
/*  388 */       this.index = i;
/*  389 */       this.offset = o;
/*      */     }
/*      */   }
/*      */   
/*      */   void skipSpace() throws ImapParseException {
/*  394 */     skipChar(' ');
/*      */   }
/*      */   
/*      */   void skipChar(char c) throws ImapParseException {
/*  398 */     if (this.index >= this.parts.size()) {
/*  399 */       throw new ImapParseException(this.tag, "unexpected end of line; expected '" + c + "'");
/*      */     }
/*  401 */     String str = ((Part)this.parts.get(this.index)).getString();
/*  402 */     if (this.offset >= str.length()) {
/*  403 */       throw new ImapParseException(this.tag, "unexpected end of line; expected '" + c + "'");
/*      */     }
/*  405 */     char got = str.charAt(this.offset);
/*  406 */     if (got == c) {
/*  407 */       this.offset += 1;
/*      */     } else {
/*  409 */       throw new ImapParseException(this.tag, "wrong character; expected '" + c + "' but got '" + got + "'");
/*      */     }
/*      */   }
/*      */   
/*      */   void skipNIL() throws ImapParseException {
/*  414 */     skipAtom("NIL");
/*      */   }
/*      */   
/*      */   void skipAtom(String atom) throws ImapParseException {
/*  418 */     if (!readATOM().equals(atom)) {
/*  419 */       throw new ImapParseException(this.tag, "did not find expected " + atom);
/*      */     }
/*      */   }
/*      */   
/*      */   String readAtom() throws ImapParseException {
/*  424 */     return readContent(ATOM_CHARS);
/*      */   }
/*      */   
/*      */   String readATOM() throws ImapParseException {
/*  428 */     return readContent(ATOM_CHARS).toUpperCase();
/*      */   }
/*      */   
/*      */   String readQuoted(Charset charset) throws ImapParseException {
/*  432 */     String result = readQuoted();
/*  433 */     if ((charset == null) || (Charsets.ISO_8859_1.equals(charset)) || (Charsets.US_ASCII.equals(charset))) {
/*  434 */       return result;
/*      */     }
/*  436 */     return new String(result.getBytes(Charsets.ISO_8859_1), charset);
/*      */   }
/*      */   
/*      */   String readQuoted() throws ImapParseException
/*      */   {
/*  441 */     String content = getCurrentLine();
/*  442 */     StringBuilder result = null;
/*      */     
/*  444 */     skipChar('"');
/*  445 */     int backslash = this.offset - 1;
/*  446 */     boolean escaped = false;
/*  447 */     for (int i = this.offset; i < content.length(); i++) {
/*  448 */       char c = content.charAt(i);
/*  449 */       if ((c > '') || (c == 0) || (c == '\r') || (c == '\n') || ((escaped) && (c != '\\') && (c != '"')))
/*  450 */         throw new ImapParseException(this.tag, "illegal character '" + c + "' in quoted string");
/*  451 */       if ((!escaped) && (c == '\\')) {
/*  452 */         if (result == null) {
/*  453 */           result = new StringBuilder();
/*      */         }
/*  455 */         result.append(content.substring(backslash + 1, i));
/*  456 */         backslash = i;
/*  457 */         escaped = true;
/*  458 */       } else { if ((!escaped) && (c == '"')) {
/*  459 */           this.offset = (i + 1);
/*  460 */           String range = content.substring(backslash + 1, i);
/*  461 */           return range;
/*      */         }
/*  463 */         escaped = false;
/*      */       }
/*      */     }
/*  466 */     throw new ImapParseException(this.tag, "unexpected end of line in quoted string");
/*      */   }
/*      */   
/*      */   private String readLiteral(Charset charset)
/*      */     throws IOException, ImapParseException
/*      */   {
/*  472 */     return new String(readLiteral().getBytes(), charset);
/*      */   }
/*      */   
/*      */   Literal readLiteral8() throws IOException, ImapParseException {
/*  476 */     if ((peekChar() == 126) && (extensionEnabled("BINARY"))) {
/*  477 */       skipChar('~');
/*      */     }
/*  479 */     return readLiteral();
/*      */   }
/*      */   
/*      */   String readAstring() throws IOException, ImapParseException {
/*  483 */     return readAstring(null);
/*      */   }
/*      */   
/*      */   String readAstring(Charset charset) throws IOException, ImapParseException {
/*  487 */     return readAstring(charset, ASTRING_CHARS);
/*      */   }
/*      */   
/*      */   private String readAstring(Charset charset, boolean[] acceptable) throws IOException, ImapParseException {
/*  491 */     int c = peekChar();
/*  492 */     if (c == -1)
/*  493 */       throw new ImapParseException(this.tag, "unexpected end of line");
/*  494 */     if (c == 123)
/*  495 */       return readLiteral(charset != null ? charset : Charsets.UTF_8);
/*  496 */     if (c != 34) {
/*  497 */       return readContent(acceptable);
/*      */     }
/*  499 */     return readQuoted(charset);
/*      */   }
/*      */   
/*      */   private String readAquoted() throws ImapParseException
/*      */   {
/*  504 */     int c = peekChar();
/*  505 */     if (c == -1)
/*  506 */       throw new ImapParseException(this.tag, "unexpected end of line");
/*  507 */     if (c != 34) {
/*  508 */       return readContent(ASTRING_CHARS);
/*      */     }
/*  510 */     return readQuoted();
/*      */   }
/*      */   
/*      */   private String readString(Charset charset) throws IOException, ImapParseException
/*      */   {
/*  515 */     int c = peekChar();
/*  516 */     if (c == -1)
/*  517 */       throw new ImapParseException(this.tag, "unexpected end of line");
/*  518 */     if (c == 123) {
/*  519 */       return readLiteral(charset != null ? charset : Charsets.UTF_8);
/*      */     }
/*  521 */     return readQuoted(charset);
/*      */   }
/*      */   
/*      */   private String readNstring(Charset charset) throws IOException, ImapParseException
/*      */   {
/*  526 */     int c = peekChar();
/*  527 */     if (c == -1)
/*  528 */       throw new ImapParseException(this.tag, "unexpected end of line");
/*  529 */     if (c == 123)
/*  530 */       return readLiteral(charset != null ? charset : Charsets.UTF_8);
/*  531 */     if (c != 34) {
/*  532 */       skipNIL();
/*  533 */       return null;
/*      */     }
/*  535 */     return readQuoted(charset);
/*      */   }
/*      */   
/*      */   String readTag() throws ImapParseException
/*      */   {
/*  540 */     return this.tag = readContent(TAG_CHARS);
/*      */   }
/*      */   
/*      */   static String parseTag(String src) throws ImapParseException
/*      */   {
/*  545 */     for (int i = 0; i < src.length(); i++) {
/*  546 */       char c = src.charAt(i);
/*  547 */       if ((c > '') || (TAG_CHARS[c] == 0)) {
/*      */         break;
/*      */       }
/*      */     }
/*  551 */     if (i > 0) {
/*  552 */       return src.substring(0, i);
/*      */     }
/*  554 */     throw new ImapParseException();
/*      */   }
/*      */   
/*      */   String readNumber() throws ImapParseException
/*      */   {
/*  559 */     return readNumber(true);
/*      */   }
/*      */   
/*      */   String readNumber(boolean zeroOK) throws ImapParseException {
/*  563 */     String number = readContent(NUMBER_CHARS);
/*  564 */     if ((number.startsWith("0")) && ((!zeroOK) || (number.length() > 1))) {
/*  565 */       throw new ImapParseException(this.tag, "invalid number: " + number);
/*      */     }
/*  567 */     return number;
/*      */   }
/*      */   
/*      */   int parseInteger(String number) throws ImapParseException {
/*      */     try {
/*  572 */       return Integer.parseInt(number);
/*      */     } catch (NumberFormatException nfe) {
/*  574 */       throw new ImapParseException(this.tag, "number out of range: " + number);
/*      */     }
/*      */   }
/*      */   
/*      */   long parseLong(String number) throws ImapParseException {
/*      */     try {
/*  580 */       return Long.parseLong(number);
/*      */     } catch (NumberFormatException nfe) {
/*  582 */       throw new ImapParseException(this.tag, "number out of range: " + number);
/*      */     }
/*      */   }
/*      */   
/*      */   byte[] readBase64(boolean skipEquals) throws ImapParseException
/*      */   {
/*  588 */     if ((skipEquals) && (peekChar() == 61)) {
/*  589 */       skipChar('=');
/*  590 */       return null;
/*      */     }
/*      */     
/*  593 */     String encoded = readContent(BASE64_CHARS, true);
/*  594 */     int padding = (4 - encoded.length() % 4) % 4;
/*  595 */     if (padding == 3) {
/*  596 */       throw new ImapParseException(this.tag, "invalid base64-encoded content");
/*      */     }
/*  598 */     while (padding-- > 0) {
/*  599 */       skipChar('=');
/*  600 */       encoded = encoded + "=";
/*      */     }
/*  602 */     return new Base64().decode(encoded.getBytes(Charsets.US_ASCII));
/*      */   }
/*      */   
/*      */   String readSequence(boolean specialsOK) throws ImapParseException {
/*  606 */     return validateSequence(readContent(SEQUENCE_CHARS), specialsOK);
/*      */   }
/*      */   
/*      */   String readSequence() throws ImapParseException {
/*  610 */     return validateSequence(readContent(SEQUENCE_CHARS), true);
/*      */   }
/*      */   
/*      */   private String validateSequence(String value, boolean specialsOK) throws ImapParseException
/*      */   {
/*  615 */     if ((value.equals("$")) && (specialsOK) && (extensionEnabled("SEARCHRES"))) {
/*  616 */       return value;
/*      */     }
/*  618 */     int last = 0;
/*  619 */     boolean colon = false;
/*  620 */     for (int i = 0; i < value.length(); i++) {
/*  621 */       char c = value.charAt(i);
/*  622 */       if ((c > '') || (c == '$') || (SEQUENCE_CHARS[c] == 0) || ((c == '*') && (!specialsOK)))
/*  623 */         throw new ImapParseException(this.tag, "illegal character '" + c + "' in sequence");
/*  624 */       if (c == '*') {
/*  625 */         if (last == 1) {
/*  626 */           throw new ImapParseException(this.tag, "malformed sequence");
/*      */         }
/*  628 */         last = 2;
/*  629 */       } else if (c == ',') {
/*  630 */         if (last == 0) {
/*  631 */           throw new ImapParseException(this.tag, "malformed sequence");
/*      */         }
/*  633 */         last = 0;
/*  634 */         colon = false;
/*  635 */       } else if (c == ':') {
/*  636 */         if ((colon) || (last == 0)) {
/*  637 */           throw new ImapParseException(this.tag, "malformed sequence");
/*      */         }
/*  639 */         last = 0;
/*  640 */         colon = true;
/*      */       } else {
/*  642 */         if ((last == 2) || ((c == '0') && (last == 0))) {
/*  643 */           throw new ImapParseException(this.tag, "malformed sequence");
/*      */         }
/*  645 */         last = 1;
/*      */       }
/*      */     }
/*  648 */     if (last == 0) {
/*  649 */       throw new ImapParseException(this.tag, "malformed sequence");
/*      */     }
/*  651 */     return value;
/*      */   }
/*      */   
/*      */   String readFolder() throws IOException, ImapParseException
/*      */   {
/*  656 */     return readFolder(false);
/*      */   }
/*      */   
/*      */   String readFolderPattern() throws IOException, ImapParseException {
/*  660 */     return readFolder(true);
/*      */   }
/*      */   
/*      */   private String readFolder(boolean isPattern) throws IOException, ImapParseException {
/*  664 */     String raw = readAstring(null, isPattern ? PATTERN_CHARS : ASTRING_CHARS);
/*  665 */     if ((raw == null) || (raw.indexOf("&") == -1))
/*  666 */       return raw;
/*      */     try {
/*  668 */       return ImapPath.FOLDER_ENCODING_CHARSET.decode(ByteBuffer.wrap(raw.getBytes(Charsets.US_ASCII))).toString();
/*      */     } catch (Exception e) {
/*  670 */       ZimbraLog.imap.debug("ignoring error while decoding folder name: %s", raw, e); }
/*  671 */     return raw;
/*      */   }
/*      */   
/*      */   List<String> readFlags() throws ImapParseException
/*      */   {
/*  676 */     List<String> tags = new ArrayList();
/*  677 */     String content = getCurrentLine();
/*  678 */     boolean parens = peekChar() == 40;
/*  679 */     if (parens) {
/*  680 */       skipChar('(');
/*  681 */     } else if (this.offset == content.length()) {
/*  682 */       throw new ImapParseException(this.tag, "missing flag list");
/*      */     }
/*  684 */     while (((!parens) || (peekChar() != 41)) && 
/*  685 */       (this.offset < content.length())) {
/*  686 */       if (!tags.isEmpty()) {
/*  687 */         skipSpace();
/*      */       }
/*  689 */       if (peekChar() == 92) {
/*  690 */         skipChar('\\');
/*  691 */         String name = readAtom();
/*  692 */         if (!SYSTEM_FLAGS.contains(name.toUpperCase())) {
/*  693 */           throw new ImapParseException(this.tag, "invalid flag: \\" + name);
/*      */         }
/*  695 */         tags.add('\\' + name);
/*      */       } else {
/*  697 */         tags.add(readAtom());
/*      */       }
/*      */       
/*  700 */       if ((parens) && (peekChar() == 41)) {
/*      */         break;
/*      */       }
/*      */     }
/*      */     
/*  705 */     if (parens) {
/*  706 */       skipChar(')');
/*      */     }
/*  708 */     return tags;
/*      */   }
/*      */   
/*      */   private Date readDate() throws ImapParseException
/*      */   {
/*  713 */     return readDate(false, false);
/*      */   }
/*      */   
/*      */   Date readDate(boolean datetime, boolean checkRange) throws ImapParseException {
/*  717 */     String dateStr = peekChar() == 34 ? readQuoted() : readAtom();
/*  718 */     if (dateStr.length() < (datetime ? 26 : 10)) {
/*  719 */       throw new ImapParseException(this.tag, "invalid date format");
/*      */     }
/*  721 */     Calendar cal = new GregorianCalendar();
/*  722 */     cal.clear();
/*      */     
/*  724 */     int pos = 0;
/*  725 */     if ((datetime) && (dateStr.charAt(0) == ' ')) {
/*  726 */       pos++;
/*      */     }
/*  728 */     int count = 2 - pos - ((datetime) || (dateStr.charAt(1) != '-') ? 0 : 1);
/*  729 */     validateDigits(dateStr, pos, count, cal, 5);
/*  730 */     pos += count;
/*  731 */     validateChar(dateStr, pos, '-');
/*  732 */     pos++;
/*  733 */     validateMonth(dateStr, pos, cal);
/*  734 */     pos += 3;
/*  735 */     validateChar(dateStr, pos, '-');
/*  736 */     pos++;
/*  737 */     validateDigits(dateStr, pos, 4, cal, 1);
/*  738 */     pos += 4;
/*      */     
/*  740 */     if (datetime) {
/*  741 */       validateChar(dateStr, pos, ' ');
/*  742 */       pos++;
/*  743 */       validateDigits(dateStr, pos, 2, cal, 10);
/*  744 */       pos += 2;
/*  745 */       validateChar(dateStr, pos, ':');
/*  746 */       pos++;
/*  747 */       validateDigits(dateStr, pos, 2, cal, 12);
/*  748 */       pos += 2;
/*  749 */       validateChar(dateStr, pos, ':');
/*  750 */       pos++;
/*  751 */       validateDigits(dateStr, pos, 2, cal, 13);
/*  752 */       pos += 2;
/*  753 */       validateChar(dateStr, pos, ' ');
/*  754 */       pos++;
/*  755 */       boolean zonesign = dateStr.charAt(pos) == '+';
/*  756 */       validateChar(dateStr, pos, zonesign ? '+' : '-');
/*  757 */       pos++;
/*  758 */       int zonehrs = validateDigits(dateStr, pos, 2, cal, -1);
/*  759 */       pos += 2;
/*  760 */       int zonemins = validateDigits(dateStr, pos, 2, cal, -1);
/*  761 */       pos += 2;
/*  762 */       cal.set(15, (zonesign ? 1 : -1) * (60 * zonehrs + zonemins) * 60000);
/*  763 */       cal.set(16, 0);
/*      */     }
/*      */     
/*  766 */     if (pos != dateStr.length()) {
/*  767 */       throw new ImapParseException(this.tag, "excess characters at end of date string");
/*      */     }
/*  769 */     Date date = cal.getTime();
/*  770 */     if ((checkRange) && (date.getTime() < 0L)) {
/*  771 */       throw new ImapParseException(this.tag, "date out of range");
/*      */     }
/*  773 */     return date;
/*      */   }
/*      */   
/*      */   private int validateDigits(String str, int pos, int count, Calendar cal, int field) throws ImapParseException {
/*  777 */     if (str.length() < pos + count) {
/*  778 */       throw new ImapParseException(this.tag, "unexpected end of date string");
/*      */     }
/*  780 */     int value = 0;
/*  781 */     for (int i = 0; i < count; i++) {
/*  782 */       char c = str.charAt(pos + i);
/*  783 */       if ((c < '0') || (c > '9')) {
/*  784 */         throw new ImapParseException(this.tag, "invalid digit in date string");
/*      */       }
/*  786 */       value = value * 10 + (c - '0');
/*      */     }
/*      */     
/*  789 */     if (field >= 0) {
/*  790 */       cal.set(field, value);
/*      */     }
/*  792 */     return value;
/*      */   }
/*      */   
/*      */   private void validateChar(String str, int pos, char c) throws ImapParseException {
/*  796 */     if (str.length() < pos + 1) {
/*  797 */       throw new ImapParseException(this.tag, "unexpected end of date string");
/*      */     }
/*  799 */     if (str.charAt(pos) != c) {
/*  800 */       throw new ImapParseException(this.tag, "unexpected character in date string");
/*      */     }
/*      */   }
/*      */   
/*      */   private void validateMonth(String str, int pos, Calendar cal) throws ImapParseException {
/*  805 */     Integer month = (Integer)MONTH_NUMBER.get(str.substring(pos, pos + 3).toUpperCase());
/*  806 */     if (month == null) {
/*  807 */       throw new ImapParseException(this.tag, "invalid month string");
/*      */     }
/*  809 */     cal.set(2, month.intValue());
/*      */   }
/*      */   
/*      */   Map<String, String> readParameters(boolean nil) throws IOException, ImapParseException
/*      */   {
/*  814 */     if (peekChar() != 40) {
/*  815 */       if (!nil) {
/*  816 */         throw new ImapParseException(this.tag, "did not find expected '('");
/*      */       }
/*  818 */       skipNIL();return null;
/*      */     }
/*      */     
/*  821 */     Map<String, String> params = new HashMap();
/*  822 */     skipChar('(');
/*      */     for (;;) {
/*  824 */       String name = readString(Charsets.UTF_8);
/*  825 */       skipSpace();
/*  826 */       params.put(name, readNstring(Charsets.UTF_8));
/*  827 */       if (peekChar() == 41) {
/*      */         break;
/*      */       }
/*  830 */       skipSpace();
/*      */     }
/*  832 */     skipChar(')');
/*  833 */     return params;
/*      */   }
/*      */   
/*      */   int readFetch(List<ImapPartSpecifier> parts) throws IOException, ImapParseException
/*      */   {
/*  838 */     boolean list = peekChar() == 40;
/*  839 */     int attributes = 0;
/*  840 */     if (list) skipChar('(');
/*      */     do {
/*  842 */       String item = readContent(FETCH_CHARS).toUpperCase();
/*  843 */       if ((!list) && (item.equals("ALL"))) {
/*  844 */         attributes = 60;
/*  845 */       } else if ((!list) && (item.equals("FULL"))) {
/*  846 */         attributes = 61;
/*  847 */       } else if ((!list) && (item.equals("FAST"))) {
/*  848 */         attributes = 56;
/*  849 */       } else if ((item.equals("BODY")) && (peekChar() != 91)) {
/*  850 */         attributes |= 0x1;
/*  851 */       } else if (item.equals("BODYSTRUCTURE")) {
/*  852 */         attributes |= 0x2;
/*  853 */       } else if (item.equals("ENVELOPE")) {
/*  854 */         attributes |= 0x4;
/*  855 */       } else if (item.equals("FLAGS")) {
/*  856 */         attributes |= 0x8;
/*  857 */       } else if (item.equals("INTERNALDATE")) {
/*  858 */         attributes |= 0x10;
/*  859 */       } else if (item.equals("UID")) {
/*  860 */         attributes |= 0x80;
/*  861 */       } else if ((item.equals("MODSEQ")) && (extensionEnabled("CONDSTORE"))) {
/*  862 */         attributes |= 0x100;
/*  863 */       } else if (item.equals("RFC822.SIZE")) {
/*  864 */         attributes |= 0x20;
/*  865 */       } else if (item.equals("RFC822.HEADER")) {
/*  866 */         parts.add(new ImapPartSpecifier(item, "", "HEADER"));
/*  867 */       } else if (item.equals("RFC822")) {
/*  868 */         attributes |= 0x1000;
/*  869 */         parts.add(new ImapPartSpecifier(item, "", ""));
/*  870 */       } else if (item.equals("RFC822.TEXT")) {
/*  871 */         attributes |= 0x1000;
/*  872 */         parts.add(new ImapPartSpecifier(item, "", "TEXT"));
/*  873 */       } else if ((item.equals("BINARY.SIZE")) && (extensionEnabled("BINARY"))) {
/*  874 */         String sectionPart = "";
/*  875 */         skipChar('[');
/*  876 */         while (peekChar() != 93) {
/*  877 */           if (!sectionPart.equals("")) {
/*  878 */             sectionPart = sectionPart + ".";skipChar('.');
/*      */           }
/*  880 */           sectionPart = sectionPart + readNumber(false);
/*      */         }
/*  882 */         skipChar(']');
/*  883 */         if (sectionPart.isEmpty()) {
/*  884 */           attributes |= 0x40;
/*      */         } else {
/*  886 */           parts.add(new ImapPartSpecifier(item, sectionPart, ""));
/*      */         }
/*  888 */       } else if ((item.equals("BODY")) || (item.equals("BODY.PEEK")) || (((item.equals("BINARY")) || (item.equals("BINARY.PEEK"))) && (extensionEnabled("BINARY"))))
/*      */       {
/*  890 */         if (!item.endsWith(".PEEK")) {
/*  891 */           attributes |= 0x1000;
/*      */         }
/*  893 */         boolean binary = item.startsWith("BINARY");
/*  894 */         skipChar('[');
/*  895 */         ImapPartSpecifier pspec = readPartSpecifier(binary, true);
/*  896 */         skipChar(']');
/*  897 */         if (peekChar() == 60) {
/*      */           try {
/*  899 */             skipChar('<');
/*  900 */             int partialStart = Integer.parseInt(readNumber());
/*  901 */             skipChar('.');
/*  902 */             int partialCount = Integer.parseInt(readNumber(false));
/*  903 */             skipChar('>');
/*  904 */             pspec.setPartial(partialStart, partialCount);
/*      */           } catch (NumberFormatException e) {
/*  906 */             throw new ImapParseException(this.tag, "invalid partial fetch specifier");
/*      */           }
/*      */         }
/*  909 */         parts.add(pspec);
/*      */       } else {
/*  911 */         throw new ImapParseException(this.tag, "unknown FETCH attribute \"" + item + '"');
/*      */       }
/*  913 */       if ((list) && (peekChar() != 41)) {
/*  914 */         skipSpace();
/*      */       }
/*  916 */     } while ((list) && (peekChar() != 41));
/*  917 */     if (list) {
/*  918 */       skipChar(')');
/*      */     }
/*  920 */     return attributes;
/*      */   }
/*      */   
/*      */   ImapPartSpecifier readPartSpecifier(boolean binary, boolean literals) throws ImapParseException, IOException {
/*  924 */     String sectionPart = "";String sectionText = "";
/*  925 */     List<String> headers = null;
/*  926 */     boolean done = false;
/*      */     
/*  928 */     while (Character.isDigit((char)peekChar())) {
/*  929 */       sectionPart = sectionPart + (sectionPart.equals("") ? "" : ".") + readNumber(false);
/*  930 */       if ((done = peekChar() != 46 ? 1 : 0) == 0) {
/*  931 */         skipChar('.');
/*      */       }
/*      */     }
/*  934 */     if ((!done) && (peekChar() != 93)) {
/*  935 */       if (binary) {
/*  936 */         throw new ImapParseException(this.tag, "section-text not permitted for BINARY");
/*      */       }
/*  938 */       sectionText = readATOM();
/*  939 */       if ((sectionText.equals("HEADER.FIELDS")) || (sectionText.equals("HEADER.FIELDS.NOT"))) {
/*  940 */         headers = new ArrayList();
/*  941 */         skipSpace();skipChar('(');
/*  942 */         while (peekChar() != 41) {
/*  943 */           if (!headers.isEmpty()) {
/*  944 */             skipSpace();
/*      */           }
/*  946 */           headers.add((literals ? readAstring() : readAquoted()).toUpperCase());
/*      */         }
/*  948 */         if (headers.isEmpty()) {
/*  949 */           throw new ImapParseException(this.tag, "header-list may not be empty");
/*      */         }
/*  951 */         skipChar(')');
/*  952 */       } else if (sectionText.equals("MIME")) {
/*  953 */         if (sectionPart.isEmpty()) {
/*  954 */           throw new ImapParseException(this.tag, "\"MIME\" is not a valid section-spec");
/*      */         }
/*  956 */       } else if ((!sectionText.equals("HEADER")) && (!sectionText.equals("TEXT"))) {
/*  957 */         throw new ImapParseException(this.tag, "unknown section-text \"" + sectionText + '"');
/*      */       }
/*      */     }
/*  960 */     ImapPartSpecifier pspec = new ImapPartSpecifier(binary ? "BINARY" : "BODY", sectionPart, sectionText);
/*  961 */     pspec.setHeaders(headers);
/*  962 */     return pspec;
/*      */   }
/*      */   
/*      */   private ImapSearch readSearchClause(Charset charset, boolean single, ImapSearch.LogicalOperation parent, int depth) throws IOException, ImapParseException
/*      */   {
/*      */     
/*  968 */     if (depth > this.maxNestingInSearchRequest) {
/*  969 */       ZimbraLog.imap.debug("search nesting too deep (depth=%s) Max allowed=%s", new Object[] { Integer.valueOf(depth), Integer.valueOf(this.maxNestingInSearchRequest) });
/*  970 */       throw new ImapSearchTooComplexException(this.tag, "Search query too complex");
/*      */     }
/*  972 */     boolean first = true;
/*  973 */     int nots = 0;
/*      */     do {
/*  975 */       if (!first) {
/*  976 */         skipSpace();
/*      */       }
/*  978 */       int c = peekChar();
/*      */       
/*  980 */       String key = c == 40 ? "" : readContent(SEARCH_CHARS).toUpperCase();
/*      */       
/*  982 */       ImapSearch.LogicalOperation target = parent;
/*  983 */       if (key.equals("NOT")) {
/*  984 */         nots++;first = false;
/*  985 */       } else { if (nots % 2 != 0) {
/*  986 */           if (NEGATED_SEARCH.containsKey(key)) {
/*  987 */             key = (String)NEGATED_SEARCH.get(key);
/*      */           } else {
/*  989 */             parent.addChild(target = new ImapSearch.NotOperation());
/*      */           }
/*      */         }
/*  992 */         nots = 0;
/*      */         
/*      */         ImapSearch child;
/*  995 */         if (key.equals("ALL")) {
/*  996 */           child = new ImapSearch.AllSearch(); } else { ImapSearch child;
/*  997 */           if (key.equals("ANSWERED")) {
/*  998 */             child = new ImapSearch.FlagSearch("\\Answered"); } else { ImapSearch child;
/*  999 */             if (key.equals("DELETED")) {
/* 1000 */               child = new ImapSearch.FlagSearch("\\Deleted"); } else { ImapSearch child;
/* 1001 */               if (key.equals("DRAFT")) {
/* 1002 */                 child = new ImapSearch.FlagSearch("\\Draft"); } else { ImapSearch child;
/* 1003 */                 if (key.equals("FLAGGED")) {
/* 1004 */                   child = new ImapSearch.FlagSearch("\\Flagged"); } else { ImapSearch child;
/* 1005 */                   if (key.equals("RECENT")) {
/* 1006 */                     child = new ImapSearch.FlagSearch("\\Recent"); } else { ImapSearch child;
/* 1007 */                     if (key.equals("NEW")) {
/* 1008 */                       child = new ImapSearch.AndOperation(new ImapSearch[] { new ImapSearch.FlagSearch("\\Recent"), new ImapSearch.NotOperation(new ImapSearch.FlagSearch("\\Seen")) }); } else { ImapSearch child;
/* 1009 */                       if (key.equals("OLD")) {
/* 1010 */                         child = new ImapSearch.NotOperation(new ImapSearch.FlagSearch("\\Recent")); } else { ImapSearch child;
/* 1011 */                         if (key.equals("SEEN")) {
/* 1012 */                           child = new ImapSearch.FlagSearch("\\Seen"); } else { ImapSearch child;
/* 1013 */                           if (key.equals("UNANSWERED")) {
/* 1014 */                             child = new ImapSearch.NotOperation(new ImapSearch.FlagSearch("\\Answered")); } else { ImapSearch child;
/* 1015 */                             if (key.equals("UNDELETED")) {
/* 1016 */                               child = new ImapSearch.NotOperation(new ImapSearch.FlagSearch("\\Deleted")); } else { ImapSearch child;
/* 1017 */                               if (key.equals("UNDRAFT")) {
/* 1018 */                                 child = new ImapSearch.NotOperation(new ImapSearch.FlagSearch("\\Draft")); } else { ImapSearch child;
/* 1019 */                                 if (key.equals("UNFLAGGED")) {
/* 1020 */                                   child = new ImapSearch.NotOperation(new ImapSearch.FlagSearch("\\Flagged")); } else { ImapSearch child;
/* 1021 */                                   if (key.equals("UNSEEN")) {
/* 1022 */                                     child = new ImapSearch.NotOperation(new ImapSearch.FlagSearch("\\Seen")); } else { ImapSearch child;
/* 1023 */                                     if (key.equals("BCC")) {
/* 1024 */                                       skipSpace();child = new ImapSearch.HeaderSearch(ImapSearch.HeaderSearch.Header.BCC, readAstring(charset)); } else { ImapSearch child;
/* 1025 */                                       if (key.equals("BEFORE")) {
/* 1026 */                                         skipSpace();child = new ImapSearch.DateSearch(ImapSearch.DateSearch.Relation.before, readDate()); } else { ImapSearch child;
/* 1027 */                                         if (key.equals("BODY")) {
/* 1028 */                                           skipSpace();child = new ImapSearch.ContentSearch(readAstring(charset)); } else { ImapSearch child;
/* 1029 */                                           if (key.equals("CC")) {
/* 1030 */                                             skipSpace();
/* 1031 */                                             child = new ImapSearch.HeaderSearch(ImapSearch.HeaderSearch.Header.CC, readAstring(charset)); } else { ImapSearch child;
/* 1032 */                                             if (key.equals("FROM")) {
/* 1033 */                                               skipSpace();
/* 1034 */                                               child = new ImapSearch.HeaderSearch(ImapSearch.HeaderSearch.Header.FROM, readAstring(charset)); } else { ImapSearch child;
/* 1035 */                                               if (key.equals("HEADER")) {
/* 1036 */                                                 skipSpace();
/* 1037 */                                                 ImapSearch.HeaderSearch.Header relation = ImapSearch.HeaderSearch.Header.parse(readAstring());
/* 1038 */                                                 skipSpace();
/* 1039 */                                                 child = new ImapSearch.HeaderSearch(relation, readAstring(charset)); } else { ImapSearch child;
/* 1040 */                                                 if (key.equals("KEYWORD")) {
/* 1041 */                                                   skipSpace();
/* 1042 */                                                   child = new ImapSearch.FlagSearch(readAtom()); } else { ImapSearch child;
/* 1043 */                                                   if (key.equals("LARGER")) {
/* 1044 */                                                     skipSpace();
/* 1045 */                                                     child = new ImapSearch.SizeSearch(ImapSearch.SizeSearch.Relation.larger, parseLong(readNumber())); } else { ImapSearch child;
/* 1046 */                                                     if ((key.equals("MODSEQ")) && (extensionEnabled("CONDSTORE"))) {
/* 1047 */                                                       skipSpace();
/* 1048 */                                                       if (peekChar() == 34) {
/* 1049 */                                                         readFolder();
/* 1050 */                                                         skipSpace();
/* 1051 */                                                         readATOM();
/* 1052 */                                                         skipSpace();
/*      */                                                       }
/* 1054 */                                                       child = new ImapSearch.ModifiedSearch(parseInteger(readNumber(true))); } else { ImapSearch child;
/* 1055 */                                                       if (key.equals("ON")) {
/* 1056 */                                                         skipSpace();
/* 1057 */                                                         child = new ImapSearch.DateSearch(ImapSearch.DateSearch.Relation.date, readDate()); } else { ImapSearch child;
/* 1058 */                                                         if ((key.equals("OLDER")) && (extensionEnabled("WITHIN"))) {
/* 1059 */                                                           skipSpace();
/* 1060 */                                                           child = new ImapSearch.RelativeDateSearch(ImapSearch.DateSearch.Relation.before, parseInteger(readNumber())); } else { ImapSearch child;
/* 1061 */                                                           if (key.equals("SENTBEFORE"))
/*      */                                                           {
/* 1063 */                                                             skipSpace();
/* 1064 */                                                             child = new ImapSearch.DateSearch(ImapSearch.DateSearch.Relation.before, readDate()); } else { ImapSearch child;
/* 1065 */                                                             if (key.equals("SENTON")) {
/* 1066 */                                                               skipSpace();
/* 1067 */                                                               child = new ImapSearch.DateSearch(ImapSearch.DateSearch.Relation.date, readDate()); } else { ImapSearch child;
/* 1068 */                                                               if (key.equals("SENTSINCE")) {
/* 1069 */                                                                 skipSpace();
/* 1070 */                                                                 child = new ImapSearch.DateSearch(ImapSearch.DateSearch.Relation.after, readDate()); } else { ImapSearch child;
/* 1071 */                                                                 if (key.equals("SINCE")) {
/* 1072 */                                                                   skipSpace();
/* 1073 */                                                                   child = new ImapSearch.DateSearch(ImapSearch.DateSearch.Relation.after, readDate()); } else { ImapSearch child;
/* 1074 */                                                                   if (key.equals("SMALLER")) {
/* 1075 */                                                                     skipSpace();
/* 1076 */                                                                     child = new ImapSearch.SizeSearch(ImapSearch.SizeSearch.Relation.smaller, parseLong(readNumber())); } else { ImapSearch child;
/* 1077 */                                                                     if (key.equals("SUBJECT")) {
/* 1078 */                                                                       skipSpace();
/* 1079 */                                                                       child = new ImapSearch.HeaderSearch(ImapSearch.HeaderSearch.Header.SUBJECT, readAstring(charset)); } else { ImapSearch child;
/* 1080 */                                                                       if (key.equals("TEXT")) {
/* 1081 */                                                                         skipSpace();
/* 1082 */                                                                         child = new ImapSearch.ContentSearch(readAstring(charset)); } else { ImapSearch child;
/* 1083 */                                                                         if (key.equals("TO")) {
/* 1084 */                                                                           skipSpace();
/* 1085 */                                                                           child = new ImapSearch.HeaderSearch(ImapSearch.HeaderSearch.Header.TO, readAstring(charset)); } else { ImapSearch child;
/* 1086 */                                                                           if (key.equals("UID")) {
/* 1087 */                                                                             skipSpace();
/* 1088 */                                                                             child = new ImapSearch.SequenceSearch(this.tag, readSequence(), true); } else { ImapSearch child;
/* 1089 */                                                                             if (key.equals("UNKEYWORD")) {
/* 1090 */                                                                               skipSpace();
/* 1091 */                                                                               child = new ImapSearch.NotOperation(new ImapSearch.FlagSearch(readAtom())); } else { ImapSearch child;
/* 1092 */                                                                               if ((key.equals("YOUNGER")) && (extensionEnabled("WITHIN"))) {
/* 1093 */                                                                                 skipSpace();
/* 1094 */                                                                                 child = new ImapSearch.RelativeDateSearch(ImapSearch.DateSearch.Relation.after, parseInteger(readNumber()));
/* 1095 */                                                                               } else if (key.equals("")) {
/* 1096 */                                                                                 skipChar('(');
/* 1097 */                                                                                 ImapSearch child = readSearchClause(charset, false, new ImapSearch.AndOperation(new ImapSearch[0]), depth);
/* 1098 */                                                                                 skipChar(')'); } else { ImapSearch child;
/* 1099 */                                                                                 if ((Character.isDigit(key.charAt(0))) || (key.charAt(0) == '*') || (key.charAt(0) == '$')) {
/* 1100 */                                                                                   child = new ImapSearch.SequenceSearch(this.tag, validateSequence(key, true), false);
/* 1101 */                                                                                 } else if (key.equals("OR")) {
/* 1102 */                                                                                   skipSpace();
/* 1103 */                                                                                   ImapSearch child = readSearchClause(charset, true, new ImapSearch.OrOperation(new ImapSearch[0]), depth);
/* 1104 */                                                                                   skipSpace();
/* 1105 */                                                                                   readSearchClause(charset, true, (ImapSearch.LogicalOperation)child, depth);
/*      */                                                                                 } else {
/* 1107 */                                                                                   throw new ImapParseException(this.tag, "unknown search tag: " + key); } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } }
/*      */         ImapSearch child;
/* 1109 */         target.addChild(child);
/* 1110 */         first = false;
/* 1111 */       } } while ((peekChar() != -1) && (peekChar() != 41) && ((nots > 0) || (!single)));
/*      */     
/* 1113 */     if (nots > 0) {
/* 1114 */       throw new ImapParseException(this.tag, "missing search-key after NOT");
/*      */     }
/* 1116 */     depth--;
/* 1117 */     return parent;
/*      */   }
/*      */   
/*      */   ImapSearch readSearch(Charset charset) throws IOException, ImapParseException {
/* 1121 */     return readSearchClause(charset, false, new ImapSearch.AndOperation(new ImapSearch[0]), 0);
/*      */   }
/*      */   
/*      */   Charset readCharset() throws IOException, ImapParseException {
/* 1125 */     String charset = readAstring();
/*      */     try {
/* 1127 */       return Charset.forName(charset);
/*      */     }
/*      */     catch (Exception e) {
/* 1130 */       throw new ImapParseException(this.tag, "BADCHARSET", "unknown charset: " + charset.replace('\r', ' ').replace('\n', ' '), true);
/*      */     }
/*      */   }
/*      */   
/*      */   abstract Literal readLiteral()
/*      */     throws IOException, ImapParseException;
/*      */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/imap/ImapRequest.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */